package cn.core.kpis.service;

import cn.core.kpis.eo.ExpressionParam;
import cn.core.kpis.mapper.ExpressionParamMapper;
import cn.core.kpis.qo.ExpressionParamQO;
import cn.core.kpis.vo.ExpressionParamVO;
import cn.core.tool.ao.DataExportAO;
import cn.core.tool.context.CoreContextData;
import cn.core.tool.event.CoreDataEvent;
import cn.core.tool.exception.CoreException;
import cn.core.tool.service.FileService;
import cn.core.tool.util.CoreTool;
import cn.core.tool.util.Paging;
import cn.core.tool.util.Param;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.google.gson.reflect.TypeToken;
import lombok.extern.log4j.Log4j2;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * 公式参数 服务
 */
@Log4j2
@Service
public class ExpressionParamService {

  @Resource
  private ApplicationEventPublisher applicationEventPublisher;

  @Resource
  private FileService fileService;

  @Resource
  private ExpressionParamMapper expressionParamMapper;

  /**
   * 公式参数 >>> 保存
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public ExpressionParam save(ExpressionParam eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      eo.setId(CoreTool.getUUID32());
      expressionParamMapper.save(eo);
      return eo;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 批量保存
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public Collection<ExpressionParam> saveBatch(Collection<ExpressionParam> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (ExpressionParam eo : eos) {
        if (CoreTool.isNullEo(eo)) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
        eo.setId(CoreTool.getUUID32());
      }
      expressionParamMapper.saveBatch(new Paging<>(), eos);
      return eos;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 修改
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public ExpressionParam update(ExpressionParam eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      ExpressionParam oeo = expressionParamMapper.pk(new ExpressionParamQO().setId(eo.getId()));
      if (CoreTool.isNullEo(oeo)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
//      if (eo.getVersions() != null ? !eo.getVersions().equals(oeo.getVersions()) : oeo.getVersions() != null ? true : false) {
//        throw new CoreException(CoreException.E_VERSIONS_ERR);
//      }
      expressionParamMapper.update(eo);
      return eo;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 批量修改
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public Collection<ExpressionParam> updateBatch(Collection<ExpressionParam> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (ExpressionParam eo : eos) {
        if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
        ExpressionParam oeo = expressionParamMapper.pk(new ExpressionParamQO().setId(eo.getId()));
        if (CoreTool.isNullEo(oeo)) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
//        if (eo.getVersions() != null ? !eo.getVersions().equals(oeo.getVersions()) : oeo.getVersions() != null ? true : false) {
//          throw new CoreException(CoreException.E_VERSIONS_ERR);
//        }
      }
      expressionParamMapper.updateBatch(new Paging<>(), eos);
      return eos;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 删除
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public void remove(ExpressionParam eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      expressionParamMapper.remove(eo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 批量删除
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public void removeBatch(Collection<ExpressionParam> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (ExpressionParam eo : eos) {
        if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
      }
      expressionParamMapper.removeBatch(eos);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 数据量
   */
  public Long count(ExpressionParamQO qo) throws Exception {
    try {
      return expressionParamMapper.count(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 主键查询
   */
  public ExpressionParam pk(ExpressionParamQO qo) throws Exception {
    try {
      if (CoreTool.isNullEo(qo) || CoreTool.isNullStr(qo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      return expressionParamMapper.pk(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 查询
   */
  public Collection<ExpressionParam> query(ExpressionParamQO qo) throws Exception {
    try {
      return expressionParamMapper.query(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 分页
   */
  public Paging<ExpressionParam> paging(Param<ExpressionParamQO> param) throws Exception {
    try {
      if (CoreTool.isNullEo(param)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      if (param.getPage() < 1 || param.getRows() < 1) {
        throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
      }
      Paging<ExpressionParam> paging = new Paging<>(param);
      if (CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        Long count = expressionParamMapper.count(null);
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(expressionParamMapper.paging(paging, null));
        }
      } else {
        Long count = expressionParamMapper.count(param.get());
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(expressionParamMapper.paging(paging, param.get()));
        }
      }
      return paging;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 业务数据量
   */
  public Long countVo(ExpressionParamQO qo) throws Exception {
    try {
      return expressionParamMapper.countVo(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 业务主键查询
   */
  public ExpressionParamVO pkVo(ExpressionParamQO qo) throws Exception {
    try {
      if (CoreTool.isNullEo(qo) || CoreTool.isNullStr(qo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      return expressionParamMapper.pkVo(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 业务查询
   */
  public Collection<ExpressionParamVO> queryVo(ExpressionParamQO qo) throws Exception {
    try {
      return expressionParamMapper.queryVo(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 业务分页
   */
  public Paging<ExpressionParamVO> pagingVo(Param<ExpressionParamQO> param) throws Exception {
    try {
      if (CoreTool.isNullEo(param)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      if (param.getPage() < 1 || param.getRows() < 1) {
        throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
      }
      Paging<ExpressionParamVO> paging = new Paging<>(param);
      if (CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        Long count = expressionParamMapper.countVo(null);
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(expressionParamMapper.pagingVo(paging, null));
        }
      } else {
        Long count = expressionParamMapper.countVo(param.get());
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(expressionParamMapper.pagingVo(paging, param.get()));
        }
      }
      return paging;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 数据导入
   */
  public Collection<ExpressionParam> dataImport(String ao) throws Exception {
    try {
      if (CoreTool.isNullStr(ao)) {
        throw new CoreException(CoreException.E_DATA_IMPORT_FILE_URL_IS_NULL_ERR);
      }
      List<ExpressionParam> allData = null;
      try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileService.getFileStreamByFileUrl(ao))) {
        ExcelReader reader = ExcelUtil.getReader(byteArrayInputStream);
        reader.addHeaderAlias("参数名", "paramName");
        reader.addHeaderAlias("参数类型", "paramType");
        reader.addHeaderAlias("sql语句Id", "sqlStrId");
        reader.addHeaderAlias("描述", "description");
        reader.addHeaderAlias("排序权重", "weightOrder");
        reader.addHeaderAlias("外键Id", "fkid");
        allData = reader.readAll(ExpressionParam.class);
        if (CoreTool.isEmpty(allData)) {
          throw new CoreException(CoreException.E_IMPORT_DATA_IS_NULL_ERR);
        }
//        CoreDataEvent typeCoreDataEvent = new CoreDataEvent("getDictNameValueMapInfoByDictKey", "type");
//        applicationEventPublisher.publishEvent(typeCoreDataEvent);
//        LinkedHashMap<String, String> typeDictNameValueMapInfo = CoreTool.isNotNullStr(typeCoreDataEvent.getData()) ? typeCoreDataEvent.getData(new TypeToken<LinkedHashMap<String, String>>(){}) : new LinkedHashMap<String, String>();
        for (ExpressionParam eo : allData) {
          eo.setId(CoreTool.getUUID32());
//          eo.setType(typeDictNameValueMapInfo.get(eo.getType()));
        }
        expressionParamMapper.saveBatch(new Paging<>(), allData);
      } catch (IOException e) {
        throw new CoreException(CoreException.E_ERR);
      }
      return allData;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 公式参数 >>> 数据导出
   */
  public String dataExport(DataExportAO<ExpressionParamQO> ao) throws Exception {
    try {
      if (CoreTool.isEmpty(ao.getDataExportFieldConf())) {
        throw new CoreException(CoreException.E_DATA_EXPORT_FIELD_CONF_IS_NULL_ERR);
      }
      Collection<ExpressionParamVO> vos = expressionParamMapper.queryVo(ao.get());
      if (CoreTool.isEmpty(vos)) {
        throw new CoreException(CoreException.E_EXPORT_DATA_IS_NULL_ERR);
      }
//      CoreDataEvent typeCoreDataEvent = new CoreDataEvent("getDictValueMapInfoByDictKey", "type");
//      applicationEventPublisher.publishEvent(typeCoreDataEvent);
//      LinkedHashMap<String, String> typeDictValueMapInfo = CoreTool.isNotNullStr(typeCoreDataEvent.getData()) ? typeCoreDataEvent.getData(new TypeToken<LinkedHashMap<String, String>>(){}) : new LinkedHashMap<String, String>();
//      for (ExpressionParamVO eo : vos) {
//        eo.setType(typeDictValueMapInfo.get(eo.getType()));
//      }
      return fileService.getFileUrlByDataExportAO(new DataExportAO<ExpressionParamVO>()
          .setBigDataExport(ao.getBigDataExport())
          .setFileModule(ao.getFileModule())
          .setFileName(ao.getFileName())
          .setDataExportFieldConf(ao.getDataExportFieldConf())
          .setData(vos));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

}
